﻿#define _CRT_SECURE_NO_WARNINGS 1
using namespace std;
#include <iostream>

//template<class T>
//class list
//{
//public:
//	//void push_back(const T& x)
//	//{
//	//	insert(end(), x);
//	//}
//
//	////不是万能引用
//	//void push_back(T&& x)
//	//{
//	//	insert(end(), move(x)); 
//	//}
//
//	//运用完美转发实现的万能引用
//	template<class X>
//	void push_back(X&& x)
//	{
//		insert(end(), forward<x> (x)));
//	}
//};

//template <class _Ty>
//_Ty&& forward(remove_reference_t<_Ty>& _Arg) noexcept
//{ // forward an lvalue as either an lvalue or an rvalue
//	return static_cast<_Ty&&>(_Arg);
//}

//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//
//template<class T>
//void Function(T&& t)
//{
//	//Fun(t); 
//	//Fun(move(t));
//	Fun(forward<T>(t));
//}
//
//int main()
//{
//	// 10是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(10); // 右值
//
//	int a;
//	// a是左值，推导出T为int&，引⽤折叠，模板实例化为void Function(int& t)
//	Function(a); // 左值
//
//	// std::move(a)是右值，推导出T为int，模板实例化为void Function(int&& t)
//	Function(std::move(a)); // 右值
//
//	const int b = 8;
//	// a是左值，推导出T为const int&，引⽤折叠，模板实例化为void Function(const int& t)
//	Function(b); // const 左值
//
//	// std::move(b)右值，推导出T为const int，模板实例化为void Function(const int&& t)
//	Function(std::move(b)); // const 右值
//
//	return 0;
//}

//template <class ...Args>
//void Print(Args&&... args)
//{
//	cout << sizeof...(args) << endl;
//}
//
//int main()
//{
//	double x = 2.2;
//	Print(); // 包⾥有0个参数
//	Print(1); // 包⾥有1个参数
//	Print(1, string("xxxxx")); // 包⾥有2个参数
//	Print(1.1, string("xxxxx"), x); // 包⾥有3个参数
//	return 0;
//}
//
//// 原理1：编译本质这⾥会结合引⽤折叠规则实例化出以下四个函数
//void Print();
//void Print(int&& arg1);
//void Print(int&& arg1, string&& arg2);
//void Print(double&& arg1, string&& arg2, double& arg3);
//
//// 原理2：更本质去看没有可变参数模板，我们实现出这样的多个函数模板才能⽀持
//// 这⾥的功能，有了可变参数模板，我们进⼀步被解放，他是类型泛化基础
//// 上叠加数量变化，让我们泛型编程更灵活。
//void Print();
//template <class T1>
//void Print(T1&& arg1);
//template <class T1, class T2>
//void Print(T1&& arg1, T2&& arg2);
//template <class T1, class T2, class T3>
//void Print(T1&& arg1, T2&& arg2, T3&& arg3);
//// ...


//void ShowList()
//{
//	// 编译器时递归的终⽌条件，参数包是0个时，直接匹配这个函数
//	cout << endl;
//}
//
//template <class T, class ...Args>
//void ShowList(T x, Args... args)
//{
//	//递归结束条件无法写成下面这样，包扩展的递归是在编译时递归，
//	// 而下面判断相等只能运行时判断
//	//if (sizeof...(args) == 0) 
//	//	return;
//
//	cout << x << " ";
//	// args是N个参数的参数包
//	// 调⽤ShowList，参数包的第⼀个传给x，剩下N-1传给第⼆个参数包
//	ShowList(args...);
//}
//
//// 编译时递归推导解析参数
//template <class ...Args>
//void Print(Args... args)
//{
//	ShowList(args...);
//}
//
//int main()
//{
	//Print();
	//Print(1);
	//Print(1, string("xxxxx"));
	//Print(1, string("xxxxx"), 2.2);
//	return 0;
//}

// Print(1, string("xxxxx"), 2.2);调⽤时
// 本质编译器将可变参数模板通过模式的包扩展，编译器推导的以下三个重载函数函数
// 
//void ShowList(double x)
//{
// cout << x << " ";
// ShowList();
//}
//
//void ShowList(string x, double z)
//{
// cout << x << " ";
// ShowList(z);
//}
//
//void ShowList(int x, string y, double z)
//{
// cout << x << " ";
// ShowList(y, z);
//}
// 
//void Print(int x, string y, double z)
//{
// ShowList(x, y, z);
//}


//template <class T>
//const T& GetArg(const T& x)
//{
//	cout << x << " ";
//	return x;
//}
//
//template <class ...Args>
//void Arguments(Args... args)
//{}
//
//template <class ...Args>
//void Print(Args... args)
//{
//	// 注意GetArg必须返回对象，这样才能组成参数包给Arguments
//	//参数包的每个参数都传给GetArg处理,处理以后返回值作为实参组成参数包传给Arguments
//	Arguments(GetArg(args)...);
//	cout << endl;
//}
//
//// 本质可以理解为编译器编译时，包的扩展模式
//// 将上⾯的函数模板扩展实例化为下⾯的函数
////void Print(int x, string y, double z)
////{
//// Arguments(GetArg(x), GetArg(y), GetArg(z));
////}
//
//int main()
//{
//	Print();
//	Print(1);
//	Print(1, string("xxxxx"));
//	Print(1, string("xxxxx"), 2.2);
//	return 0;
//}

#include <string>
#include <assert.h>

namespace wusaqi
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		const_iterator begin() const
		{
			return _str;
		}
		const_iterator end() const
		{
			return _str + _size;
		}
		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
			cout << "string(char* str)-构造" << endl;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		void swap(string& s)
		{
			::swap(_str, s._str);
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}

		// 拷贝构造
		string(const string& s)
			:_str(nullptr)
		{
			cout << "string(const string& s) -- 拷贝构造" << endl;
			reserve(s._capacity);
			for (auto ch : s)
			{
				push_back(ch);
			}
		}

		// 移动构造
		string(string&& s)
		{
			cout << "string(string&& s) -- 移动构造" << endl;
			swap(s);
		}

		//拷贝赋值
		string& operator=(const string& s)
		{
			cout << "string& operator=(const string& s) -- 拷贝赋值" << endl;
			if (this != &s)
			{
				_str[0] = '\0';
				_size = 0;
				reserve(s._capacity);
				for (auto ch : s)
				{
					push_back(ch);
				}
			}
			return *this;
		}

		// 移动赋值
		string& operator=(string&& s)
		{
			cout << "string& operator=(string&& s) -- 移动赋值" << endl;
			swap(s);
			return *this;
		}
		~string()
		{
			//仅在string对象持有资源时才析构
			if (_str) 
			{
				cout << "~string() -- 析构" << endl;
				delete[] _str;
				_str = nullptr;
			}
		}
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				if (_str)
				{
					strcpy(tmp, _str);
					delete[] _str;
				}
				_str = tmp;
				_capacity = n;
			}
		}
		void push_back(char ch)
		{
			if (_size >= _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 4 : _capacity *
					2;
				reserve(newcapacity);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		const char* c_str() const
		{
			return _str;
		}
		size_t size() const
		{
			return _size;
		}
	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
	};
}

#include<list>

// emplace_back总体⽽⾔是更⾼效，推荐以后使⽤emplace系列替代insert和push系列
int main()
{
	//list<wusaqi::string> lt;
	//// 传左值，跟push_back⼀样，⾛构造(对象s1)+拷⻉构造
	//wusaqi::string s1("111111111111");
	//lt.emplace_back(s1);
	//cout << "*********************************" << endl;

	//// 传右值，跟push_back⼀样，⾛移动构造
	//lt.emplace_back(move(s1));
	//cout << "*********************************" << endl;

	//// 直接把构造string参数包往下传，直接⽤string参数包构造string
	//// 这⾥达到的效果是push_back做不到的

	////构造临时对象(隐式类型转换)+移动构造
	//lt.push_back("111111111111");    //匹配push_back右值引用版本
	//cout << "*********************************" << endl;
	////构造
	//lt.emplace_back("111111111111"); //将万能引用模板参数推导为const char*&，最后引用折叠成const char*&
	//cout << "*********************************" << endl;

	list<pair<wusaqi::string, int>> lt1;
	// 跟push_back⼀样
	// 构造pair + 拷⻉/移动构造pair到list的节点中data上
	//pair<wusaqi::string, int> kv("苹果", 1);
	//lt1.push_back(kv);
	//lt1.emplace_back(kv);
	//cout << "*********************************" << endl;

	//// 跟push_back⼀样
	////lt1.push_back(move(kv));
	//lt1.emplace_back(move(kv));
	//cout << "*********************************" << endl;

	// 直接把构造pair参数包往下传，直接⽤pair参数包构造pair
	// 这⾥达到的效果是push_back做不到的
	lt1.push_back({ "苹果", 1 });
	//lt1.emplace_back({ "苹果", 1 }); //编译不通过
	lt1.emplace_back("苹果", 1);
	cout << "*********************************" << endl;

	return 0;
}



